#!/bin/bash
#========================================================================
# Author: YSLin
# Email: 
# File Name: redirect.sh
# Description: 
# 	標準輸入　　(stdin) ：代碼為 0 ，使用 < 或 << ； /dev/fd/0
# 	標準輸出　　(stdout)：代碼為 1 ，使用 > 或 >> ； /dev/fd/1
# 	標準錯誤輸出(stderr)：代碼為 2 ，使用 2> 或 2>> ；
# 	垃圾桶黑洞裝置與特殊寫法 使用 2> /dev/null 或 > /dev/null 居多
# 	n>&m	means redirect FD n to the same places as FD m. Eg, 2>&1 means send STDERR to the same place that STDOUT is going to.
#
# 1. < 是input，> 是output
# 2.<預設值是0，>預設值是1。即<與0<同，>與 1>同。下面的例子若有疑問，可試著代入展開。
#	>&n: 即1>&n，也就是將stdout複制給 file descriptor n (使用dup(2))
#	<&n: 即0<&n，將file descriptor n 複製到stdin
#	<&-: 即0<&-，關閉stdin
#	>&-: 即1>&-，關閉stdout
# 3. 使用exec來redirect
#   
# Edit History: 
#   2010-12-16    File created.
#========================================================================

#1> filename #Redirect stdout to file "filename"
#1>>filename #Redirect and append stdout to file "filename"
#2> filename #Redirect stderr to file "filename"
#2>>filename ##Redirect and append stderr to file "filename"
#&> filename ##Redirect both stderr and stdout to file "filename"
#The last syntax is not recognized by KSH.
#To redirect both stderr and stdout to file "filename", the syntax is :
#1>filename 2>&1 or
#>filename 2>&1

#將錯誤的資料丟棄，螢幕上顯示正確的資料
find /home -name .bashrc 2> /dev/null

#將指令的資料(stdin and stderr)全部寫入名為 list 的檔案中
find /home -name .bashrc > list 2>&1     
find /home -name .bashrc &> list        

#I want both(stdout/stderr) stored into the file.
./sout.py 2&> test.txt

#At last, I want both display and redirect to a file:
#redirect stderr to stdout, then `tee` redirect stdout to file and stdout
./sout.py 2>&1 | tee test.txt

#將ls輸出的結果導向其他檔案
#using nohup; this allows you to close and reopen your session without losing any background processes in the... process.
nohup ls&

#紀錄所有stdout
#`script`

#tee可以把input 導向 stdout和file
ls | tee "list" | grep "red"

#每300秒輸出結果
while :
do
	date
	who
	sleep 300
done >> logfile

#將輸出一次給某個檔案
(
date
who
) > logfile

# 使用grouping的例子
# 只顯示同時存在於資料夾dir1與dir2中的檔案
{ ls dir1; ls dir2; } | sort | uniq -d


# 使用exec的例子

echo "Terminal - line 1"   # 顯示到畫面上

# 使用「3>&1」之後，file handle3會被連到現在的標準輸出(=終端)                                                                                 
# (這麼做的目的是，等一下才能恢復原狀)。另外，用「>file」之後
# 標準輸出會被重新導向到檔案file。
exec 3>&1 >file

echo "File - line 1"       # 寫到檔案
echo "File - line 2"       # 寫到檔案

# 使用「>&3」之後，標準輸出會被連到file handle3(=終端)(也就是恢復原狀了)
# 使用「3>&-」之後，file handle3就被關閉了。
exec >&3 3>&-

echo "Terminal - line 2"   # 寫到畫面


################################################
# Name: printERROR
# Desc: prints an message to STDERR
# Args: $@ -> message to print
################################################
printERROR() {
	echo "ERROR:" $@ >&2
}



do_stop () {
	#backup stdin to fd 9, then redirect infile as stdin
	exec 9<&0 <infile
	#restore stdin from fd 9, then close fd 9
	exec 0<&9 9<&-
}


#========================================================================
# 使用/dev/fd/1, 來表示stdout
#========================================================================
# 在本例中，sort會從/dev/fd/0(標準輸入)取得資料，
# 將結果寫到/dev/fd/1(標準輸出)中。也就是和「cat $0 | sort」是一樣意思。
# $0是表示script file自己本身的檔名。

cat $0 | sort -o /dev/fd/1 /dev/fd/0      
